/*******************************************************************************
 * Copyright (c) 2010 European Software Institute - Tecnalia.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Author - Adri�n Noguero (adrian.noguero@esi.es)
 *     
 *******************************************************************************/

package es.esi.gemde.modeltransformator.service;

import java.io.IOException;
import java.net.URI;
import java.util.HashMap;
import java.util.List;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.swt.graphics.Image;

import es.esi.gemde.modeltransformator.exceptions.NoPreviousTransformationException;
import es.esi.gemde.modeltransformator.exceptions.NoSuchEngineException;
import es.esi.gemde.modeltransformator.exceptions.TransformationEngineException;

/**
 * Interface of the Model Transformation Service of GEMDE.
 * It provides a generic interface that abstracts the user from the transformation engines underneath. 
 * The service implementation can be accessed via {@link es.esi.gemde.modeltransformator.ModelTransformatorPlugin#getService()}
 *
 * @author Adrian Noguero (adrian.noguero@tecnalia.com)
 * @version 1.0
 * @since 1.0
 * 
 * @see {@link es.esi.gemde.modeltransformator.ModelTransformatorPlugin#getService()}
 *
 */
public interface IModelTransformationService {

	/**
	 * Adds a transformation implementation to the repository.
	 * 
	 * @param newTransformation the new transformation to be added.
	 * @throws IllegalArgumentException if the provided transformation is null or if a transformation with the same name is exists already in the repository.
	 * 
	 * @see {@link TransformationFactory#createTransformation(String, String, java.io.File)}
	 */
	public void addTransformation(ITransformation newTransformation) throws IllegalArgumentException;
	
	
	/**
	 * This method adds a transformation to the repository for just one session. Transformations added using this method cannot be removed from the repository until the service is disposed.
	 * It is intended to be used by other plug-ins that require to load transformations and protect them.
	 * 
	 * @param newTransformation the new transformation to be added.
	 * @throws IllegalArgumentException if the provided transformation is null or if a transformation with the same name is exists already in the repository.
	 */
	public void addSessionTransformation(ITransformation newTransformation) throws IllegalArgumentException;
	
	/**
	 * Returns true if the provided transformation name is already registered in the repository. False otherwise.
	 * 
	 * @param transformationName the name of the transformation to be checked.
	 * @return true if a transformation with the given name has been found in the repository. False otherwise.
	 */
	public boolean transformationExists(String transformationName);
	
	/**
	 * Removes the transformation with the given name from the repository. If the transformation is not found nothing is done.
	 * 
	 * @param name the name of the transformation to be removed.
	 */
	public void removeTransformation(String name);
	
	/**
	 * Returns an snapshot of the transformation repository in an array.
	 * 
	 * @return the current transformations in the repository.
	 */
	public ITransformation[] getTransformationRepository();
	
	/**
	 * Returns an array of String containing the names of all the transformation engines registered in the service.
	 * 
	 * @return the names of the transformation engines available.
	 */
	public String [] getAvailableEngines();
	
	/**
	 * Registers a new engine in the model transformation service.
	 * If an engine with the same name is already registered nothing will be done.
	 * 
	 * @param engine the engine to be registered.
	 * @throws IllegalArgumentException if a null engine was provided or if the name of the engine is not valid.
	 */
	public void registerEngine(ITransformationEngine engine) throws IllegalArgumentException;
	
	/**
	 * Removes a transformation engine from the transformation engine repository. 
	 * If the provided name is not found nothing will be done.
	 * 
	 * @param engineName the name of the engine to be unregistered.
	 */
	public void unregisterEngine(String engineName);
	
	/**
	 * This method will run a registered transformation on a registered transformation engine with the given inputs. Results will be stored in the given path.
	 * 
	 * @param inputs a list of {@link EObject}s that will be used as inputs for the transformation engine.
	 * @param transformationName the name of the registered transformation to be launched.
	 * @param engineName the name of the registered engine that will run the transformation.
	 * @param outputPath the location where the transformation engine will drop the generated outputs.
	 * @return the status returned by the model transformation engine.
	 * @throws IllegalArgumentException if a null value was provided for any of the names or if the transformation name provided does not match any of the transformations registered in the service.
	 * @throws TransformationEngineException if an exception was raised during the transformation process.
	 * @throws NoSuchEngineException if the selected transformation engine is not registered in the service.
	 * @throws IOException if the provided output path is not a valid directory.
	 */
	public IStatus executeTransformation (List<EObject> inputs, String transformationName, String engineName, String outputPath) throws IllegalArgumentException, TransformationEngineException, NoSuchEngineException, IOException;
	
	/**
	 * This method will run again the last valid transformation executed by the transformation service.
	 * 
	 * @return the status returned by the model transformation engine.
	 * @throws TransformationEngineException if an exception was raised during the transformation process.
	 * @throws NoPreviousTransformationException if no previous transformations have been successfully launched.
	 */
	public IStatus executeLastTransformation () throws TransformationEngineException, NoPreviousTransformationException;
	
	/**
	 * Returns the icon image related to a specific transformation engine
	 * 
	 * @param name the name of the engine.
	 * @return the icon image.
	 */
	public Image getEngineImage(String name);
	
	/**
	 * This method checks if a transformation resource is valid for a particular engine.
	 * 
	 * @param engine the name of the engine to which the transformation resource is related.
	 * @param transformationURI the URI of the transformation resource.
	 * @return true of the transformation resource is valid for the given engine. False otherwise.
	 */
	public boolean checkTransformationValidity(String engine, URI transformationURI);
	
	/**
	 * This method checks if a set of transformation resources is valid for a particular engine.
	 * 
	 * @param engine the name of the engine to which the transformation resource is related.
	 * @param transformationURIs the list of URI of the transformation resources.
	 * @return true of the transformation resource is valid for the given engine. False otherwise.
	 */
	public boolean checkTransformationValidity(String engine, List<URI> transformationURIs);
	
	/**
	 * Check if the input and output parameters of the transformation are valid for the current transformation engine.
	 * 
	 * @param engine the name of the engine
	 * @param inputs the map of the input params
	 * @param outputs the map of the output params
	 * @param options the options map
	 * @return true if the provided parameters are valid.
	 */
	public boolean checkTransformationParamsValidity(String engine, HashMap<String, EClass> inputs, HashMap<String, EClass> outputs, HashMap<String, String> options);


	/**
	 * Get the selected transformation reference from the repository
	 * 
	 * @param transformationName. The transformation name.
	 * @return the transformation object or null is none exists.
	 */
	public ITransformation getTransformation(String transformationName);
	
}
